from django.shortcuts import render, redirect
from django.http import HttpResponse
from django.views.generic import View
from django.core.urlresolvers import reverse
import re
from django.db import IntegrityError
from users.models import User, Address
from goods.models import GoodsSKU
from django.core.mail import send_mail
from django.conf import settings
from itsdangerous import TimedJSONWebSignatureSerializer as sss
from itsdangerous import SignatureExpired
from celery_tasks.tasks import send_active_email
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from utils.views import LoginRequired
from django_redis import get_redis_connection
import json


# Create your views here.
#
# class UserInfoView(LoginRequired, View):
#     def get(self, request):
#
#         user = request.user
#
#         try:
#             address = user.address_set.latest('create_time')
#         except Address.DoesNotExist:
#             address = None
#         # 创建redis 连接对象
#
#         redis_connection = get_redis_connection('default')
#         # 从redis 中获取用户 浏览的商品 sku_id
#         sku_ids = redis_connection.lrange('history_%s' % user.id, 0, 4)
#
#         sku_list = []
#
#         for id in sku_ids:
#             sku = GoodsSKU.objects.filter(id=id)
#             sku_list.append(sku)
#
#         context = {'address': address, 'sku_list': sku_list}
#         return render(request, 'user_center_info.html', context)

class UserInfoView(LoginRequired, View):
    """用户中心"""

    def get(self, request):
        """查询用户信息和地址信息"""

        # 从request中获取user对象，中间件从验证请求中的用户，所以request中带有user
        user = request.user

        try:
            # 查询用户地址：根据创建时间排序，取第1个地址
            address = user.address_set.latest('create_time')
        except Address.DoesNotExist:
            # 如果地址信息不存在
            address = None

        # 创建redis连接对象
        redis_connection = get_redis_connection('default')
        # 从Redis中获取用户浏览商品的sku_id，在redis中需要维护商品浏览顺序[8,2,5]
        sku_ids = redis_connection.lrange('history_%s' % user.id, 0, 4)

        # 从数据库中查询商品sku信息,范围在sku_ids中
        # skuList = GoodsSKU.objects.filter(id__in=sku_ids)
        # 问题：经过数据库查询后得到的skuList，就不再是redis中维护的顺序了,而是[2,5,8]
        # 需求：保证经过数据库查询后，依然是[8,2,5]
        sku_list = []
        for sku_id in sku_ids:
            sku = GoodsSKU.objects.get(id=sku_id)
            sku_list.append(sku)

        # 构造上下文
        context = {
            'address': address,
            'sku_list': sku_list,
        }

        # 调出并渲染模板
        return render(request, 'user_center_info.html', context)


class AddressView(LoginRequired, View):
    def get(self, request):
        """提供用户地址页面"""
        # 获取登陆的user

        user = request.user

        # address = Address.objects.filter(user=user).order_by('-create_time')[0]
        # address = user.address_set.order_by('-create_time')[0]
        try:
            address = user.address_set.latest('create_time')
        except Address.DoesNotExist:
            address = None

        context = {'address': address}
        return render(request, 'user_center_site.html', context)

    def post(self, request):
        """修改地址信息"""

        user = request.user
        recv_mobile = request.POST.get('receiver_mobile')
        zip_code = request.POST.get('zip_code')
        addr = request.POST.get('detail_addr')
        recv_name = request.POST.get('receiver_name')

        if all([recv_mobile, zip_code, addr, recv_name]):
            Address.objects.create(
                user=user,
                receiver_name=recv_name,
                detail_addr=addr,
                zip_code=zip_code,
                receiver_mobile=recv_mobile
            )

        return redirect(reverse("users:address"))


"""
第一种  麻烦 代码没有重用!
        if request.user.is_authenticated():
            return render(request,'user_center_site.html')
        else:
            return HttpResponse('请登陆后访问!')
"""


class LogoutView(View):
    def get(self, request):
        logout(request)

        return redirect(reverse('goods:index'))


class LoginView(View):
    def get(self, request):
        return render(request, 'login.html')

    def post(self, request):
        user_name = request.POST.get('username')
        pwd = request.POST.get('pwd')

        if not all([user_name, pwd]):
            return redirect(reverse('users:login'))

        user = authenticate(username=user_name, password=pwd)

        if user is None:
            return render(request, 'login.html', {'errmsg': '账号或密码错误!'})

        if user.is_active is False:
            return render(request, 'login.html', {'errmsg': '用户未激活'})

        remembered = request.POST.get('remembered')
        login(request, user)

        if remembered != 'on':
            request.session.set_expiry(0)
        else:
            request.session.set_expiry(864000)

        # 3.1415926 5358979323 846264 3383952702 88429716939937 5105820974944

        # 需求：在登陆页面跳转前，将cookie和redis中的购物车数据合并到redis中

        # 1 先获取cookie 中的购物车数据
        cart_json = request.POST.get('cart')
        if cart_json is not None:
            cart_dict_cookie = json.loads(cart_json)
        else:
            cart_dict_cookie = {}

        # 2 获取redis 中的购物车信息
        redis_coon = get_redis_connection('default')
        cart_dict_redis = redis_coon.hgetall('cart_%s' % user.id)

        # 合并购物车上商品信息
        #  1 cookie 存在 redis 也有 累加

        #  2 cookie 存在 redis 中没有 生成新的购物车数据!

        # 将cookie 中的购物车数据合并到redis

        for sku_id, count in cart_dict_cookie.items():
            # 提示：由于redis中的键与值都是bytes类型，cookie中的sku_id是字符串类型
            # 需要将cookie中的sku_id字符串转成bytes   encode()编码 decode 解码
            sku_id = sku_id.encode()
            # 如果 循环中的cookie 中的 sku_id 在redis 中也有 可以用字典 值 =['键']  取值
            if sku_id in cart_dict_redis:
                origin_count = cart_dict_redis[sku_id]
                # 用count 去添加origin_count
                count += int(origin_count)

            # 如果cookie 中的商品在redis 中有, 就累加count 赋值 反之 直接赋值在cookie中的count
            cart_dict_redis[sku_id] = count

        # 将合并后的redis 数据 设置到redis 中: redis_conn.hmset()不能传入空字典
        if cart_dict_redis:
            redis_coon.hmset('cart_%s' % user.id, cart_dict_redis)

        next = request.GET.get('next')

        if next is None:
            response = redirect(reverse('goods:index'))
        else:
            if next == '/orders/place':
                response = redirect('/cart')
            else:
                response = redirect(next)
        response.delete_cookie('cart')
        return response


class ActiveView(View):
    """用户激活"""

    def get(self, request, token):
        ser = sss(settings.SECRET_KEY, 3600)
        try:
            # 使用序列化器, 获取token 明文信息, 需要判断签名是否过期
            result = ser.loads(token)
        except SignatureExpired:
            return HttpResponse('激活链接已过期!')

        user_id = result.get('confirm')

        try:
            user = User.objects.get(id=user_id)
        except User.DoesNotExist:
            return HttpResponse('用户不存在')

        user.is_active = True
        user.save()

        return redirect(reverse('users:login'))
        # return HttpResponse('激活成功!')


class RegisterView(View):
    def get(self, request):
        return render(request, 'register.html')

    def post(self, request):
        # 获取表单中的信息!
        user_name = request.POST.get('user_name')
        pwd = request.POST.get('pwd')

        cpwd = request.POST.get('cpwd')
        email = request.POST.get('email')
        allow = request.POST.get('allow')

        if not all([user_name, pwd, email]):
            return redirect(reverse('users:register'))
        # if not all([user_name, pwd, email]):
        #     return redirect(reverse('users:register'))


        if not re.match(r"^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$", email):
            return render(request, 'register.html', {'errmsg': '邮箱地址错误!'})

        if pwd != cpwd:
            return render(request, 'register.html', {'errmsg': '两次密码不一致!'})

        # 判断是否勾选协议
        if allow != 'on':
            return render(request, 'register.html', {'errmsg': '没有勾选协议!'})

        try:
            user = User.objects.create_user(user_name, email, pwd)
        except IntegrityError:
            return render(request, 'register.html', {'errmsg': '用户已注册'})
        user.is_active = False

        user.save()

        token = user.generate_active_token()

        send_active_email.delay(email, user_name, token)

        # return HttpResponse('这里是实现注册逻辑!')
        return redirect(reverse('users:login'))
